/**
 * 
 */
package string.passed;

/**
 * @author Michael
 * Validate if a given string is numeric.
 * Some examples:
 * "0" => true
 * " 0.1 " => true
 * "abc" => false
 * "1 a" => false
 * "2e10" => true
 * Note: It is intended for the problem statement to be ambiguous. 
 * You should gather all requirements up front before implementing one.
 */
public class ValidNumber {

	public boolean isNumber(String s) {
		if (s == null)
			return false;

		s = s.trim();

		int position = 0;
		while (position < s.length()
				&& (s.charAt(position) == '+' || s.charAt(position) == '-')) {
			if (position > 0)
				return false;
			position++;
		}

		s = s.substring(position);

		boolean foundDot = false;
		boolean foundExp = false;
		boolean isNumber = false;

		for (int i = 0; i < s.length(); i++) {
			int ch = s.charAt(i);
			if (Character.isDigit(ch)) {
				isNumber = true;
			} else if (ch == '.') {
				if (foundDot || foundExp)
					return false;
				foundDot = true;
			} else if (ch == 'e' || ch == 'E') {
				if (foundExp || !isNumber)
					return false;
				foundExp = true;
				isNumber = false;
			} else if (ch == '+' || ch == '-') {
				int preCh = s.charAt(i - 1);
				if (preCh != 'e' && preCh != 'E')
					return false;
			} else
				return false;

		}

		return isNumber;
	}

	// http://dl.dropbox.com/u/19732851/LeetCode/ValidNumber.html
	/**
	
	 */
	public static boolean isValid(String s) {
		if (s == null)
			return false;

		s = s.trim(); // trim space around the string

		// check if only space
		if (s.length() == 0)
			return false;

		// skip +/- sign
		int position;
		for (position = 0; position < s.length(); ++position) {
			if (s.charAt(position) == '+' || s.charAt(position) == '-') {
				if (position > 0) {
					if (s.charAt(position) == s.charAt(position - 1))
						return false;
				}
			} else
				break;
		}
		s = s.substring(position);

		boolean foundDot = false; // sign for decimal
		boolean foundExp = false; // sign for e
		boolean isNumber = false;

		for (int i = 0; i < s.length(); ++i) {
			if (Character.isDigit(s.charAt(i))) {
				isNumber = true;
			} else if (s.charAt(i) == '.') { // . must be before e and cannot be repeated
				if (foundDot || foundExp)
					return false;
				foundDot = true;
			} else if (s.charAt(i) == 'e' || s.charAt(i) == 'E') {
				if (foundExp || !isNumber) { // e must have leading number and cannot be repeated
					return false;
				}
				foundExp = true;
			} else if (s.charAt(i) == '+' || s.charAt(i) == '-') { // +/- must be
				if (s.charAt(i - 1) != 'e' && s.charAt(i - 1) != 'E')
					return false;
			} else
				return false;
		}

		return isNumber;
	}

	// from justion
	public static boolean isValid1(String s) {
		if (s == null || s.length() == 0)
			return false;
		int pos = 0;
		while (pos < s.length() && s.charAt(pos) == ' ')
			pos++;
		if (pos == s.length())
			return false;
		if (!Character.isDigit(s.charAt(pos)) && s.charAt(pos) != '+'
				&& s.charAt(pos) != '-')
			return false;
		boolean plus = s.charAt(pos) == '+';
		boolean minus = s.charAt(pos) == '-';
		if (plus || minus) {
			pos++;
			if (pos == s.length())
				return false;
			else if (s.charAt(pos) == '-' && minus || s.charAt(pos) == '+'
					&& plus)
				return false;
			else if (s.charAt(pos) == '-' || s.charAt(pos) == '+') {
				pos++;
				if (pos == s.length())
					return false;
			}
		}
		boolean decimal = false, scientific = false;
		boolean digit = false;
		while (pos < s.length()) {
			char c = s.charAt(pos);
			if (c == ' ')
				break;
			else if (c == 'e' || c == 'E')
				if (!digit || scientific)
					return false;
				else
					scientific = true;
			else if (c == '.')
				if (decimal)
					return false;
				else
					decimal = true;
			else if (Character.isDigit(c))
				digit = true;
			else
				return false;
			pos++;
		}
		while (pos < s.length()) {
			if (s.charAt(pos) == ' ')
				pos++;
			else
				return false;
		}
		return true;
	}

	static boolean isNumeric(String str, boolean allowDecimal) {
		if (str == null || str.isEmpty()) {
			return false;
		}

		boolean result = true;

		if (str.startsWith("-") || str.startsWith("+")) {
			str = str.substring(1);
		}

		if (allowDecimal) {
			boolean findDecimal = false;
			for (int i = 0, size = str.length(); i < size; ++i) {
				if (str.charAt(i) == '.' && !findDecimal) {
					findDecimal = true;
				} else if (!Character.isDigit(str.charAt(i))) {
					result = false;
					break;
				}
				//				else {
				//					result = result & Character.isDigit(str.charAt(i));
				//				}
			}
		} else {
			for (int i = 0, size = str.length(); i < size; ++i) {

				if (!Character.isDigit(str.charAt(i))) {
					result = false;
					break;
				}
				//				result = result & Character.isDigit(str.charAt(i));
			}
		}

		return result;
	}

	static boolean isInteger(String str) {
		if (str == null || str.length() == 0)
			return false;

		boolean result = true;
		str = str.trim();

		// check sign
		int index = 0;
		if (str.charAt(0) == '+' || str.charAt(0) == '-') {
			index++;
		}

		for (; index < str.length(); ++index) {
			if (!Character.isDigit(str.charAt(index))) {
				result = false;
			}
		}

		return result;
	}

	static boolean isDecimal(String str) {
		if (str == null)
			return false;

		str = str.trim();
		if (str.length() == 0)
			return false;

		boolean result = false;
		int index = 0;

		// check sign
		if (str.charAt(index) == '+' || str.charAt(index) == '-') {
			index++;
		}

		boolean foundDecimal = false;
		for (; index < str.length(); ++index) {
			if (Character.isDigit(str.charAt(index))) {
				result = true;
			} else if (str.charAt(index) == '.' && !foundDecimal) {
				foundDecimal = true;
			} else {
				result = false;
			}
		}

		return result;
	}

	/**
	 * 
	 */
	public ValidNumber() {
		// TODO Auto-generated constructor stub
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String[] ss = { " 0.1", " 0.1 ", "abc", "1 a", "2e10", "+1", "-1",
				"++1", "--1", "+-1", "-+1", "+-", "-+-1", "+-+1", "1..1",
				"12345", "12345.678  ", "123E456E", "", " ", "   " };
		for (String s : ss)
			System.out.println(s + ": " + isValid(s));
	}

}
